<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CSV marker map - use ?csv=URL to CSV to populate</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
<style>
html, body {
  height: 100%;
  margin: 0;
}
.custom-marker {
  background-color: darkred;
  border-radius: 50%;
  border: 1px solid white;
}
</style>
</head>
<body>
<div id="map" style="width: 100%; height: 100%;"></div>
<script>
function toPoint(s) {
  return s.split(",").map(parseFloat);
}
async function load() {
  let params = new URLSearchParams(location.search);
  let center = params.get('center') || '0,0';
  let initialZoom = params.get('zoom');
  let zoom = parseInt(initialZoom || '2', 10);
  let q = params.get('q');
  let markers = params.getAll('marker');
  let csvUrl = params.get('csv');
  let markerColor = params.get('color') || 'blue';

  let styleElement = document.getElementsByTagName('style')[0];
  // Get the CSS rule for .custom-marker
  let cssRules = styleElement.sheet.cssRules;
  let customMarkerRule;

  for (var i = 0; i < cssRules.length; i++) {
    if (cssRules[i].selectorText === '.custom-marker') {
      customMarkerRule = cssRules[i];
      break;
    }
  }
  if (customMarkerRule) {
    customMarkerRule.style.backgroundColor = markerColor;
  }

  let map = L.map('map', { zoomControl: false }).setView(toPoint(center), zoom);
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
    detectRetina: true
  }).addTo(map);
  if (q && !params.get('center')) {
    let response = await fetch(
      `https://nominatim.openstreetmap.org/search.php?q=${encodeURIComponent(q)}&format=jsonv2`
    )
    let data = await response.json();
    let bounds = [
      [data[0].boundingbox[0],data[0].boundingbox[2]],
      [data[0].boundingbox[1],data[0].boundingbox[3]]
    ];
    map.fitBounds(bounds);
    // User-provided zoom over-rides this
    if (initialZoom) {
      map.setZoom(parseInt(initialZoom));
    }
  }
  map.on('moveend zoomend', () => {
    // Update URL bar with current location
    let newZoom = map.getZoom();
    let center = map.getCenter();
    let u = new URLSearchParams();
    markers.forEach(s => u.append('marker', s));
    u.append('center', `${center.lat},${center.lng}`);
    u.append('zoom', newZoom);
    if (csvUrl) {
      u.append('csv', csvUrl);
    }
    history.replaceState(null, null, '?' + u.toString());
  });
  markers.forEach(s => {
    L.marker(toPoint(s)).addTo(map);
  });
  if (csvUrl) {
    await new Promise((resolve, reject) => {
      let script = document.createElement('script');
      script.src = 'https://unpkg.com/papaparse@5.3.0/papaparse.min.js';
      script.onload = resolve;
      script.onerror = reject;
      document.head.appendChild(script);
    });
    Papa.parse(csvUrl, {
      download: true,
      header: true,
      complete: results => {
        results.data.forEach(row => {
          if (row.latitude && row.longitude) {
            L.marker([parseFloat(row.latitude), parseFloat(row.longitude)], {
              icon: L.divIcon({
                className: 'custom-marker',
                iconSize: [10, 10],
                iconAnchor: [5, 5]
              })
            }).addTo(map);
          }
        });
      }
    });
  }
}
load();
</script>
</body>
</html>
